package ${basePackageName}.domain.jpa.entity;

<#if common>
import com.zy.explore.common.interfaces.frm.SortFieldFrm;
import com.zy.explore.common.infrastructure.base.jpa.BaseEntity;
<#else>
import ${basePackageName}.infrastructure.base.jpa.BaseEntity;
</#if>
import ${basePackageName}.domain.jpa.repository.${tableClassNamePrefix}Repository;
import ${basePackageName}.interfaces.frm.${tableClassNamePrefix}QueryFrm;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Setter;
import lombok.Getter;
import lombok.ToString;
import lombok.NoArgsConstructor;
import org.hibernate.Hibernate;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import lombok.extern.slf4j.Slf4j;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.criteria.Predicate;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
<#if pkType == 'String'>
import org.hibernate.annotations.GenericGenerator;
</#if>

/**
 * 表(${tableName})对应的Jpa ORM实体类
 *
 * @author ${authorName}
 * @date ${dateTime}
 */
@Slf4j
@Entity
@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DynamicUpdate
@DynamicInsert
@Table(name = "${tableName}")
public class <#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix} extends BaseEntity<${tableClassNamePrefix}Repository, <#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix}, ${pkType}> {
<#list tableColumns as column>
    <#if column.isPk>
    /**
     * 主键
     */
    @Id
        <#if pkType == 'String'>
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "uuid_generator")
            <#if common>
    @GenericGenerator(name = "uuid_generator", strategy = "com.zy.explore.common.infrastructure.util.MyUUIDGenerator")
            <#else>
    @GenericGenerator(name = "uuid_generator", strategy = "${basePackageName}.infrastructure.util.MyUUIDGenerator")
            </#if>
        <#else>
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "JDBC")
        </#if>
    @Column(name = "${column.columnName}", insertable = false, updatable = false, nullable = false)
    private ${column.propType} ${column.propName};
    <#else>
    /**
     * ${(column.columnComment != '')? string('${column.columnComment}','TODO 补充字段注释')}
     */
    @Column(name = "${column.columnName}")
    private ${column.propType} ${column.propName};
    </#if>

</#list>
    private static ${tableClassNamePrefix}Repository repository() {
        return Holder.REPO;
    }

    private static final class Holder {
        private static final ${tableClassNamePrefix}Repository REPO = getRepository(${tableClassNamePrefix}Repository.class, <#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix}.class);
    }

    /**
     * Frm转Specification查询条件
     *
     * @param frm 查询参数对象
     * @return 返回JPA所需的查询条件对象
     */
    public static Specification<<#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix}> getSpecification(${tableClassNamePrefix}QueryFrm frm) {
        // TODO 请按实际需求组装查询条件
        log.warn("TODO 请按实际需求组装查询条件");
        if (frm.getPageNum() == null) {
            frm.setPageNum(1);
        }
        if (frm.getPageSize() == null) {
            frm.setPageSize(10);
        }
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<>();
                <#list tableColumns as column>
                    <#if column.propType == 'Integer' || column.propType == 'Long' || column.propType == 'Float' || column.propType == 'Double' || column.propType == 'Boolean'>
            if(frm.get${column.firstUpperPropName}() != null) {
                predicateList.add(criteriaBuilder.equal(root.get("${column.propName}"), frm.get${column.firstUpperPropName}()));
            }
                    <#elseif column.propType == 'Date'>
            if(!StringUtils.isEmpty(frm.get${column.firstUpperPropName}Begin())) {
                predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("${column.propName}").as(String.class), frm.get${column.firstUpperPropName}Begin()));
            }
            if(!StringUtils.isEmpty(frm.get${column.firstUpperPropName}End())) {
                predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("${column.propName}").as(String.class), frm.get${column.firstUpperPropName}End()));
            }
                    <#elseif column.propType == 'String'>
            if (!StringUtils.isEmpty(frm.get${column.firstUpperPropName}())) {
                predicateList.add(criteriaBuilder.like(root.get("${column.propName}"), "%" + frm.get${column.firstUpperPropName}() + "%"));
            }
                    </#if>
                </#list>
            return criteriaBuilder.and(predicateList.toArray(new Predicate[0]));
        };
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
            return false;
        }
        <#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix} entity = (<#if prefixJpa??>${prefixJpa}</#if>${tableClassNamePrefix}) o;
        return id != null && Objects.equals(id, entity.id);
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }
}